﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Queries;
using Castle.Components.Validator;

namespace Matriculex.Dominio
{
    [ActiveRecord("usuario"), JoinedBase, Serializable]
    public abstract class Usuario : RemovableEntityWithId<Usuario> 
    {

        // construtor vazio necessário para o ActiveRecord
        protected Usuario() { }

        public Usuario(string nome, string email)
        {
            this.Nome = nome;
            this.Email = email;
            this.Senha = "";
        }

        [Property]
        [ValidateNonEmpty("Nome do Usuário não pode ser vazio.")]
        public string Nome { get; set; }

        [Property]
        [ValidateNonEmpty("Email do Usuário não pode ser vazio.")]
        public string Email { get; set; }

        [Property]
        [ValidateNonEmpty("Senha do Usuário não pode ser vazia.")]
        public string Senha
        {

            get;
            private set;

        }

        public void SetSenha(string senha)
        {
            if(string.IsNullOrEmpty(senha))
                throw new ValidationException("A senha não pode ser vazia.");

            this.Senha = new Encriptador().ComputeHash(senha);
        }

        public static Usuario Autentica(string email, string senhaDigitada)
        {
            SimpleQuery<Usuario> q = new SimpleQuery<Usuario>(@"
                from Usuario u
                where u.Email = :email and u.Ativado = 1");
            q.SetParameter("email", email);
            Usuario[] usuarios = q.Execute();
            System.Diagnostics.Debug.Assert(usuarios.Length <= 1);
            if (usuarios.Length == 1)
            {
                if(new Encriptador().VerifyHash(senhaDigitada, usuarios[0].Senha))
                    return usuarios[0];
            }
                
            return null;
        }

        public string GerarSenha()
        {

            string senhaNaoCriptada = new RandomPassword().ToString();

            this.SetSenha(senhaNaoCriptada);

            return senhaNaoCriptada;
        }


        public override void Save()
        {
            Usuario[] usuarios = FindAllByProperty("Email", this.Email);
            // se é um novo curso
            if (this.IsTransient())
            {
                if (usuarios != null && usuarios.Length > 0)
                    throw new ValidationException("Já existe um usuário com este email");
            }
            else
            {
                // se vamos salvar
                if (usuarios != null && usuarios.Length > 0)
                {
                    // se há mais de 1 curso com este código (inconsistencia)
                    // ou o Id do curso de código existen não é este
                    if (usuarios.Length > 1 || usuarios[0].Id != this.Id)
                        throw new ValidationException("Já existe um usuário com este email");
                }
            }

            base.Save();
        }

    }
}
